3ddb79bdff-gj-jFGKjOejeHLqL8Lg xen/common/Makefile
3e397e66AyyD5fYraAySWuwi9uqSXg xen/common/ac_timer.c
3ddb79bdrqnW93GR9gZk1OJe1qK-iQ xen/common/brlock.c
-3fb10d07GscSWPKxBqpvNfU-dYfa0g xen/common/console.c
4022a73c_BbDFd2YJ_NQYVvKX5Oz7w xen/common/debug-linux.c
3fa152581E5KhrAtqZef2Sr5NKTz4w xen/common/debug.c
3ddb79bdLX_P6iB7ILiblRLWvebapg xen/common/dom0_ops.c
3e9c248afxxsnAzIt2na7Ej24yNFzg xen/drivers/cdrom/Makefile
3e9c248ajUkn2W3n4vgm72Hp2ftZ8A xen/drivers/cdrom/cdrom.c
3e4a8cb7alzQCDKS7MlioPoHBKYkdQ xen/drivers/char/Makefile
+4049e6bfNSIq7s7OV-Bd69QD0RpR2Q xen/drivers/char/console.c
+3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/keyboard.c
3e4a8cb7nMChlro4wvOBo76n__iCFA xen/drivers/char/serial.c
-3e4a8cb7WmiYdC-ASGiCSG_CL8vsqg xen/drivers/char/xen_kbd.c
3ddb79bdhcqD9ebrslr0O0oHqTiiXg xen/drivers/ide/Makefile
3e9c248aCM6Lex1Am8_NJIeesN4kKg xen/drivers/ide/ide-cd.c
3e9c248aFfSNR_hl-WQBbv-R9CTgzg xen/drivers/ide/ide-cd.h
401c0592pLrp_aCbQRo9GXiYQQaVVA xenolinux-2.4.25-sparse/include/linux/timer.h
3e5a4e68W_hpMlM3u_-QOKMp3gzcwQ xenolinux-2.4.25-sparse/init/do_mounts.c
3e5a4e68TJJavrunYwTAnLRSBxSYqQ xenolinux-2.4.25-sparse/kernel/panic.c
-3f1056a9LXNTgSzITNh1mb-MIKV1Ng xenolinux-2.4.25-sparse/kernel/printk.c
3f9d4b44247udoqWEgFkaHiWv6Uvyg xenolinux-2.4.25-sparse/kernel/time.c
401c059bjLBFYHRD4Py2uM3eA1D4zQ xenolinux-2.4.25-sparse/kernel/timer.c
3eba8f878XjouY21EkQBXwYBsPsipQ xenolinux-2.4.25-sparse/lndir-rel
.long SYMBOL_NAME(do_set_timer_op) /* 20 */
.long SYMBOL_NAME(do_event_channel_op)
.long SYMBOL_NAME(do_xen_version)
+ .long SYMBOL_NAME(do_serial_io)
.rept NR_syscalls-((.-hypervisor_call_table)/4)
.long SYMBOL_NAME(do_ni_syscall)
.endr
+++ /dev/null
-/*
- * console.c
- *
- * read domain console output buffer ring in Xen
- *
- */
-
-#include <xeno/console.h>
-#include <asm-i386/uaccess.h>
-
-console_ring_t console_ring = {
- .len = 0
-};
-
-long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
-{
- unsigned int len;
-
- len = (console_ring.len < count) ? console_ring.len : count;
-
- if ( copy_to_user((char *)str, console_ring.buf, len) )
- return -EFAULT;
-
- if ( cmd & CONSOLE_RING_CLEAR ) {
- console_ring.len = 0;
- }
-
- return len;
-}
#include <asm/msr.h>
#include <asm/pdb.h>
#include <xeno/trace.h>
+#include <xeno/console.h>
extern unsigned int alloc_new_dom_mem(struct task_struct *, unsigned int);
case DOM0_READCONSOLE:
{
- extern long read_console_ring(unsigned long,
- unsigned int, unsigned int);
ret = read_console_ring(op->u.readconsole.str,
op->u.readconsole.count,
op->u.readconsole.cmd);
}
*dst = '\0';
- /* HACK: Give up the VGA console iff the Xenolinux DOM0 wants it. */
- if ( strstr(cmdline, "tty0") != NULL )
- vgacon_enabled = 0;
+ /* NB: Give up the VGA console iff the Xenolinux DOM0 wants it. */
+ console_endboot(strstr(cmdline, "tty0") != NULL);
/* Reinstate the caller's page tables. */
write_cr3_counted(pagetable_val(current->mm.pagetable));
*/
#include <stdarg.h>
+#include <xeno/config.h>
#include <xeno/lib.h>
#include <xeno/errno.h>
#include <xeno/spinlock.h>
kmem_cache_t *task_struct_cachep;
-static int xpos, ypos;
-static unsigned char *video = __va(0xB8000);
-
-int sercon_handle = -1;
-int vgacon_enabled = 0;
-
-spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
-
struct e820entry {
unsigned long addr_lo, addr_hi; /* start of memory segment */
unsigned long size_lo, size_hi; /* size of memory segment */
unsigned long type; /* type of memory segment */
};
-static void init_vga(void);
void start_of_day(void);
/* opt_console: comma-separated list of console outputs. */
struct task_struct *new_dom;
dom0_createdomain_t dom0_params;
unsigned long max_page;
- unsigned char *cmdline, *p;
+ unsigned char *cmdline;
module_t *mod;
void *heap_start;
int i;
/* We initialise the serial devices very early so we can get debugging. */
serial_init_stage1();
- /* Where should console output go? */
- for ( p = opt_console; p != NULL; p = strchr(p, ',') )
- {
- if ( *p == ',' )
- p++;
- if ( strncmp(p, "com", 3) == 0 )
- sercon_handle = parse_serial_handle(p);
- else if ( strncmp(p, "vga", 3) == 0 )
- vgacon_enabled = 1;
- }
-
- /* Set up VGA console output, if it was enabled. */
- init_vga();
+ init_console();
/* HELLO WORLD --- start-of-day banner text. */
printk(XEN_BANNER);
XEN_VERSION, XEN_SUBVERSION, XEN_EXTRAVERSION,
XEN_COMPILE_BY, XEN_COMPILE_DOMAIN,
XEN_COMPILER, XEN_COMPILE_DATE);
+ set_printk_prefix("(XEN) ");
if ( opt_ser_baud != 0 )
printk("**WARNING**: Xen option 'ser_baud=' is deprecated! "
startup_cpu_idle_loop();
}
-
-/*********************************
- * Various console code follows...
- */
-
-/* VGA text (mode 3) definitions. */
-#define COLUMNS 80
-#define LINES 25
-#define ATTRIBUTE 7
-
-/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
-static void cls(void)
-{
- memset(video, 0, COLUMNS * LINES * 2);
- xpos = ypos = 0;
- outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
-}
-
-static int detect_video(void *video_base)
-{
- volatile u16 *p = (volatile u16 *)video_base;
- u16 saved1 = p[0], saved2 = p[1];
- int video_found = 1;
-
- p[0] = 0xAA55;
- p[1] = 0x55AA;
- if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
- video_found = 0;
-
- p[0] = 0x55AA;
- p[1] = 0xAA55;
- if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
- video_found = 0;
-
- p[0] = saved1;
- p[1] = saved2;
-
- return video_found;
-}
-
-static int detect_vga(void)
-{
- /*
- * Look at a number of well-known locations. Even if video is not at
- * 0xB8000 right now, it will appear there when we set up text mode 3.
- *
- * We assume if there is any sign of a video adaptor then it is at least
- * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
- *
- * These checks are basically to detect headless server boxes.
- */
- return (detect_video(__va(0xA0000)) ||
- detect_video(__va(0xB0000)) ||
- detect_video(__va(0xB8000)));
-}
-
-/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
-static void init_vga(void)
-{
- /* The following VGA state was saved from a chip in text mode 3. */
- static unsigned char regs[] = {
- /* Sequencer registers */
- 0x03, 0x00, 0x03, 0x00, 0x02,
- /* CRTC registers */
- 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
- 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
- 0xb9, 0xa3, 0xff,
- /* Graphic registers */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
- /* Attribute registers */
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
- 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
- };
-
- int i, j = 0;
- volatile unsigned char tmp;
-
- if ( !vgacon_enabled )
- return;
-
- if ( !detect_vga() )
- {
- printk("No VGA adaptor detected!\n");
- vgacon_enabled = 0;
- return;
- }
-
- tmp = inb(0x3da);
- outb(0x00, 0x3c0);
-
- for ( i = 0; i < 5; i++ )
- outw((regs[j++] << 8) | i, 0x3c4);
-
- /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
- outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
-
- for ( i = 0; i < 25; i++ )
- outw((regs[j++] << 8) | i, 0x3d4);
-
- for ( i = 0; i < 9; i++ )
- outw((regs[j++] << 8) | i, 0x3ce);
-
- for ( i = 0; i < 21; i++ )
- {
- tmp = inb(0x3da);
- outb(i, 0x3c0);
- outb(regs[j++], 0x3c0);
- }
-
- tmp = inb(0x3da);
- outb(0x20, 0x3c0);
-
- cls();
-}
-
-
-static void put_newline(void)
-{
- xpos = 0;
- ypos++;
-
- if (ypos >= LINES)
- {
- static char zeroarr[2*COLUMNS] = { 0 };
- ypos = LINES-1;
- memcpy((char*)video,
- (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
- memcpy((char*)video + (LINES-1)*2*COLUMNS,
- zeroarr, 2*COLUMNS);
- }
-}
-
-
-static void putchar_console(int c)
-{
- if ( !vgacon_enabled )
- return;
-
- if ( c == '\n' )
- {
- put_newline();
- }
- else
- {
- video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF;
- video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
- if ( ++xpos >= COLUMNS )
- put_newline();
- }
-}
-
-
-void putchar_console_ring(int c)
-{
- if ( console_ring.len < CONSOLE_RING_SIZE )
- console_ring.buf[console_ring.len++] = (char)c;
-}
-
-
-static inline void __putstr(const char *str)
-{
- int c;
- serial_puts(sercon_handle, str);
- while ( (c = *str++) != '\0' )
- {
- putchar_console(c);
- putchar_console_ring(c);
- }
-}
-
-
-void printf(const char *fmt, ...)
-{
- va_list args;
- char buf[128];
- const char *p = fmt;
- unsigned long flags;
-
- /*
- * If the format string contains '%' descriptors then we have to parse it
- * before printing it. We parse it into a fixed-length buffer. Long
- * strings should therefore _not_ contain '%' characters!
- */
- if ( strchr(fmt, '%') != NULL )
- {
- va_start(args, fmt);
- (void)vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
- p = buf;
- }
-
- spin_lock_irqsave(&console_lock, flags);
- __putstr(p);
- spin_unlock_irqrestore(&console_lock, flags);
-}
-
-
-long do_console_write(char *str, unsigned int count)
-{
-#define SIZEOF_BUF 256
- unsigned char safe_str[SIZEOF_BUF+1];
- unsigned char single_line[SIZEOF_BUF+2];
- unsigned char line_header[30];
- unsigned char *p;
- unsigned char c;
- unsigned long flags;
- int j;
-
- if ( count == 0 )
- return 0;
-
- if ( count > SIZEOF_BUF )
- count = SIZEOF_BUF;
-
- if ( copy_from_user(safe_str, str, count) )
- return -EFAULT;
- safe_str[count] = '\0';
-
- sprintf(line_header, "DOM%llu: ", current->domain);
-
- p = safe_str;
- while ( *p != '\0' )
- {
- j = 0;
-
- while ( (c = *p++) != '\0' )
- {
- if ( c == '\n' )
- break;
- if ( (c < 32) || (c > 126) )
- continue;
- single_line[j++] = c;
- }
-
- single_line[j++] = '\n';
- single_line[j++] = '\0';
-
- spin_lock_irqsave(&console_lock, flags);
- __putstr(line_header);
- __putstr(single_line);
- spin_unlock_irqrestore(&console_lock, flags);
- }
-
- return 0;
-}
-
-
-/*********************************
- * Debugging/tracing/error-report.
- */
-
-void panic(const char *fmt, ...)
-{
- va_list args;
- char buf[128];
- unsigned long flags;
- extern void machine_restart(char *);
-
- va_start(args, fmt);
- (void)vsnprintf(buf, sizeof(buf), fmt, args);
- va_end(args);
-
- /* Spit out multiline message in one go. */
- spin_lock_irqsave(&console_lock, flags);
- __putstr("\n****************************************\n");
- __putstr(buf);
- __putstr("Aieee! CPU");
- sprintf(buf, "%d", smp_processor_id());
- __putstr(buf);
- __putstr(" is toast...\n");
- __putstr("****************************************\n\n");
- __putstr("Reboot in five seconds...\n");
- spin_unlock_irqrestore(&console_lock, flags);
-
- mdelay(5000);
- machine_restart(0);
-}
-
-
-void __out_of_line_bug(int line)
-{
- printk("kernel BUG in header file at line %d\n", line);
- BUG();
- for ( ; ; ) continue;
-}
-
-
-/*********************************
+/*
* Simple syscalls.
*/
return key_table[key].handler;
}
-static void serial_rx(unsigned char c, struct pt_regs *regs)
-{
- key_handler *handler;
- if ( (handler = get_key_handler(c)) != NULL )
- (*handler)(c, NULL, regs);
-}
-
static void show_handlers(u_char key, void *dev_id, struct pt_regs *regs)
{
int i;
add_key_handler('m', reaudit_pages, "re-audit pages");
add_key_handler('M', audit_all_pages, "audit all pages");
#endif
-
- serial_set_rx_handler(sercon_handle, serial_rx);
}
--- /dev/null
+/******************************************************************************
+ * console.c
+ *
+ * Emergency console I/O for Xen and the domain-0 guest OS.
+ *
+ * Copyright (c) 2002-2004, K A Fraser.
+ */
+
+#include <stdarg.h>
+#include <xeno/config.h>
+#include <xeno/lib.h>
+#include <xeno/errno.h>
+#include <xeno/event.h>
+#include <xeno/spinlock.h>
+#include <xeno/console.h>
+#include <xeno/serial.h>
+#include <xeno/keyhandler.h>
+#include <asm/uaccess.h>
+
+static int xpos, ypos;
+static unsigned char *video = __va(0xB8000);
+
+#define CONSOLE_RING_SIZE 16392
+typedef struct console_ring_st
+{
+ char buf[CONSOLE_RING_SIZE];
+ unsigned int len;
+} console_ring_t;
+static console_ring_t console_ring;
+
+static char printk_prefix[16] = "";
+
+static int sercon_handle = -1;
+static int vgacon_enabled = 0;
+
+spinlock_t console_lock = SPIN_LOCK_UNLOCKED;
+
+
+/*
+ * *******************************************************
+ * *************** OUTPUT TO VGA CONSOLE *****************
+ * *******************************************************
+ */
+
+/* VGA text (mode 3) definitions. */
+#define COLUMNS 80
+#define LINES 25
+#define ATTRIBUTE 7
+
+/* Clear the screen and initialize VIDEO, XPOS and YPOS. */
+static void cls(void)
+{
+ memset(video, 0, COLUMNS * LINES * 2);
+ xpos = ypos = 0;
+ outw(10+(1<<(5+8)), 0x3d4); /* cursor off */
+}
+
+static int detect_video(void *video_base)
+{
+ volatile u16 *p = (volatile u16 *)video_base;
+ u16 saved1 = p[0], saved2 = p[1];
+ int video_found = 1;
+
+ p[0] = 0xAA55;
+ p[1] = 0x55AA;
+ if ( (p[0] != 0xAA55) || (p[1] != 0x55AA) )
+ video_found = 0;
+
+ p[0] = 0x55AA;
+ p[1] = 0xAA55;
+ if ( (p[0] != 0x55AA) || (p[1] != 0xAA55) )
+ video_found = 0;
+
+ p[0] = saved1;
+ p[1] = saved2;
+
+ return video_found;
+}
+
+static int detect_vga(void)
+{
+ /*
+ * Look at a number of well-known locations. Even if video is not at
+ * 0xB8000 right now, it will appear there when we set up text mode 3.
+ *
+ * We assume if there is any sign of a video adaptor then it is at least
+ * VGA-compatible (surely noone runs CGA, EGA, .... these days?).
+ *
+ * These checks are basically to detect headless server boxes.
+ */
+ return (detect_video(__va(0xA0000)) ||
+ detect_video(__va(0xB0000)) ||
+ detect_video(__va(0xB8000)));
+}
+
+/* This is actually code from vgaHWRestore in an old version of XFree86 :-) */
+static void init_vga(void)
+{
+ /* The following VGA state was saved from a chip in text mode 3. */
+ static unsigned char regs[] = {
+ /* Sequencer registers */
+ 0x03, 0x00, 0x03, 0x00, 0x02,
+ /* CRTC registers */
+ 0x5f, 0x4f, 0x50, 0x82, 0x55, 0x81, 0xbf, 0x1f, 0x00, 0x4f, 0x20,
+ 0x0e, 0x00, 0x00, 0x01, 0xe0, 0x9c, 0x8e, 0x8f, 0x28, 0x1f, 0x96,
+ 0xb9, 0xa3, 0xff,
+ /* Graphic registers */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0e, 0x00, 0xff,
+ /* Attribute registers */
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3a,
+ 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x0c, 0x00, 0x0f, 0x08, 0x00
+ };
+
+ int i, j = 0;
+ volatile unsigned char tmp;
+
+ if ( !vgacon_enabled )
+ return;
+
+ if ( !detect_vga() )
+ {
+ printk("No VGA adaptor detected!\n");
+ vgacon_enabled = 0;
+ return;
+ }
+
+ tmp = inb(0x3da);
+ outb(0x00, 0x3c0);
+
+ for ( i = 0; i < 5; i++ )
+ outw((regs[j++] << 8) | i, 0x3c4);
+
+ /* Ensure CRTC registers 0-7 are unlocked by clearing bit 7 of CRTC[17]. */
+ outw(((regs[5+17] & 0x7F) << 8) | 17, 0x3d4);
+
+ for ( i = 0; i < 25; i++ )
+ outw((regs[j++] << 8) | i, 0x3d4);
+
+ for ( i = 0; i < 9; i++ )
+ outw((regs[j++] << 8) | i, 0x3ce);
+
+ for ( i = 0; i < 21; i++ )
+ {
+ tmp = inb(0x3da);
+ outb(i, 0x3c0);
+ outb(regs[j++], 0x3c0);
+ }
+
+ tmp = inb(0x3da);
+ outb(0x20, 0x3c0);
+
+ cls();
+}
+
+static void put_newline(void)
+{
+ xpos = 0;
+ ypos++;
+
+ if (ypos >= LINES)
+ {
+ static char zeroarr[2*COLUMNS] = { 0 };
+ ypos = LINES-1;
+ memcpy((char*)video,
+ (char*)video + 2*COLUMNS, (LINES-1)*2*COLUMNS);
+ memcpy((char*)video + (LINES-1)*2*COLUMNS,
+ zeroarr, 2*COLUMNS);
+ }
+}
+
+static void putchar_console(int c)
+{
+ if ( !vgacon_enabled )
+ return;
+
+ if ( c == '\n' )
+ {
+ put_newline();
+ }
+ else
+ {
+ video[(xpos + ypos * COLUMNS) * 2] = c & 0xFF;
+ video[(xpos + ypos * COLUMNS) * 2 + 1] = ATTRIBUTE;
+ if ( ++xpos >= COLUMNS )
+ put_newline();
+ }
+}
+
+
+/*
+ * ********************************************************
+ * *************** ACCESS TO CONSOLE RING *****************
+ * ********************************************************
+ */
+
+static void putchar_console_ring(int c)
+{
+ if ( console_ring.len < CONSOLE_RING_SIZE )
+ console_ring.buf[console_ring.len++] = (char)c;
+}
+
+long read_console_ring(unsigned long str, unsigned int count, unsigned cmd)
+{
+ unsigned int len;
+
+ len = (console_ring.len < count) ? console_ring.len : count;
+
+ if ( copy_to_user((char *)str, console_ring.buf, len) )
+ return -EFAULT;
+
+ if ( cmd & CONSOLE_RING_CLEAR )
+ console_ring.len = 0;
+
+ return len;
+}
+
+
+/*
+ * *******************************************************
+ * *************** ACCESS TO SERIAL LINE *****************
+ * *******************************************************
+ */
+
+/* Characters received over the serial line are buffered for domain 0. */
+#define SERIAL_RX_SIZE 128
+#define SERIAL_RX_MASK(_i) ((_i)&(SERIAL_RX_SIZE-1))
+static char serial_rx_ring[SERIAL_RX_SIZE];
+static unsigned int serial_rx_cons, serial_rx_prod;
+
+/* CTRL-a switches input direction between Xen and DOM0. */
+#define CTRL_A 0x01
+
+static void serial_rx(unsigned char c, struct pt_regs *regs)
+{
+ key_handler *handler;
+ unsigned long cpu_mask;
+ struct task_struct *p;
+ static char *input_str[2] = { "DOM0", "Xen" };
+ static int xen_rx = 1; /* FALSE => serial input passed to domain 0. */
+
+ if ( c == CTRL_A )
+ {
+ xen_rx = !xen_rx;
+ printk("*** Serial input -> %s "
+ "(type 'CTRL-a' to switch input to %s).\n",
+ input_str[xen_rx], input_str[!xen_rx]);
+ }
+ else if ( xen_rx )
+ {
+ if ( (handler = get_key_handler(c)) != NULL )
+ (*handler)(c, NULL, regs);
+ }
+ else if ( (serial_rx_prod-serial_rx_cons) != SERIAL_RX_SIZE )
+ {
+ serial_rx_ring[SERIAL_RX_MASK(serial_rx_prod)] = c;
+ if ( serial_rx_prod++ == serial_rx_cons )
+ {
+ p = find_domain_by_id(0); /* only DOM0 reads the serial buffer */
+ cpu_mask = mark_guest_event(p, _EVENT_CONSOLE);
+ guest_event_notify(cpu_mask);
+ put_task_struct(p);
+ }
+ }
+}
+
+long do_serial_io(int cmd, int count, char *buffer)
+{
+ char *kbuf;
+ long rc;
+
+ /* Only domain-0 may access the emrgency console. */
+ if ( current->domain != 0 )
+ return -EPERM;
+
+ switch ( cmd )
+ {
+ case SERIALIO_write:
+ if ( count > (PAGE_SIZE-1) )
+ count = PAGE_SIZE-1;
+ if ( (kbuf = (char *)get_free_page(GFP_KERNEL)) == NULL )
+ return -ENOMEM;
+ kbuf[count] = '\0';
+ rc = count;
+ if ( copy_from_user(kbuf, buffer, count) )
+ rc = -EFAULT;
+ else
+ serial_puts(sercon_handle, kbuf);
+ free_page((unsigned long)kbuf);
+ break;
+ case SERIALIO_read:
+ rc = 0;
+ while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
+ {
+ if ( put_user(serial_rx_ring[SERIAL_RX_MASK(serial_rx_cons)],
+ &buffer[rc]) )
+ {
+ rc = -EFAULT;
+ break;
+ }
+ rc++;
+ serial_rx_cons++;
+ }
+ break;
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
+}
+
+
+/*
+ * *****************************************************
+ * *************** GENERIC CONSOLE I/O *****************
+ * *****************************************************
+ */
+
+static inline void __putstr(const char *str)
+{
+ int c;
+ serial_puts(sercon_handle, str);
+ while ( (c = *str++) != '\0' )
+ {
+ putchar_console(c);
+ putchar_console_ring(c);
+ }
+}
+
+void printf(const char *fmt, ...)
+{
+ static char buf[1024];
+ static int start_of_line = 1;
+
+ va_list args;
+ char *p, *q;
+ unsigned long flags;
+
+ spin_lock_irqsave(&console_lock, flags);
+
+ va_start(args, fmt);
+ (void)vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ p = buf;
+ while ( (q = strchr(p, '\n')) != NULL )
+ {
+ *q = '\0';
+ if ( start_of_line )
+ __putstr(printk_prefix);
+ __putstr(p);
+ __putstr("\n");
+ start_of_line = 1;
+ p = q + 1;
+ }
+
+ if ( *p != '\0' )
+ {
+ if ( start_of_line )
+ __putstr(printk_prefix);
+ __putstr(p);
+ start_of_line = 0;
+ }
+
+ spin_unlock_irqrestore(&console_lock, flags);
+}
+
+void set_printk_prefix(const char *prefix)
+{
+ strcpy(printk_prefix, prefix);
+}
+
+/*
+ * This hypercall is deprecated. Only permit its use in debug environments.
+ */
+long do_console_write(char *str, unsigned int count)
+{
+#ifndef NDEBUG
+#define SIZEOF_BUF 256
+ unsigned char safe_str[SIZEOF_BUF+1];
+ unsigned char single_line[SIZEOF_BUF+2];
+ unsigned char line_header[30];
+ unsigned char *p;
+ unsigned char c;
+ unsigned long flags;
+ int j;
+
+ if ( count == 0 )
+ return 0;
+
+ if ( count > SIZEOF_BUF )
+ count = SIZEOF_BUF;
+
+ if ( copy_from_user(safe_str, str, count) )
+ return -EFAULT;
+ safe_str[count] = '\0';
+
+ sprintf(line_header, "DOM%llu: ", current->domain);
+
+ p = safe_str;
+ while ( *p != '\0' )
+ {
+ j = 0;
+
+ while ( (c = *p++) != '\0' )
+ {
+ if ( c == '\n' )
+ break;
+ if ( (c < 32) || (c > 126) )
+ continue;
+ single_line[j++] = c;
+ }
+
+ single_line[j++] = '\n';
+ single_line[j++] = '\0';
+
+ spin_lock_irqsave(&console_lock, flags);
+ __putstr(line_header);
+ __putstr(single_line);
+ spin_unlock_irqrestore(&console_lock, flags);
+ }
+
+ return 0;
+#else
+ return -ENOSYS;
+#endif
+}
+
+void init_console(void)
+{
+ extern unsigned char opt_console[];
+ unsigned char *p;
+
+ /* Where should console output go? */
+ for ( p = opt_console; p != NULL; p = strchr(p, ',') )
+ {
+ if ( *p == ',' )
+ p++;
+ if ( strncmp(p, "com", 3) == 0 )
+ sercon_handle = parse_serial_handle(p);
+ else if ( strncmp(p, "vga", 3) == 0 )
+ vgacon_enabled = 1;
+ }
+
+ init_vga();
+
+ serial_set_rx_handler(sercon_handle, serial_rx);
+}
+
+void console_endboot(int disable_vga)
+{
+ if ( disable_vga )
+ vgacon_enabled = 0;
+ /* Serial input is directed to DOM0 by default. */
+ serial_rx(CTRL_A, NULL);
+}
+
+
+/*
+ * **************************************************************
+ * *************** Debugging/tracing/error-report ***************
+ * **************************************************************
+ */
+
+void panic(const char *fmt, ...)
+{
+ va_list args;
+ char buf[128];
+ unsigned long flags;
+ extern void machine_restart(char *);
+
+ va_start(args, fmt);
+ (void)vsnprintf(buf, sizeof(buf), fmt, args);
+ va_end(args);
+
+ /* Spit out multiline message in one go. */
+ spin_lock_irqsave(&console_lock, flags);
+ __putstr("\n****************************************\n");
+ __putstr(buf);
+ __putstr("Aieee! CPU");
+ sprintf(buf, "%d", smp_processor_id());
+ __putstr(buf);
+ __putstr(" is toast...\n");
+ __putstr("****************************************\n\n");
+ __putstr("Reboot in five seconds...\n");
+ spin_unlock_irqrestore(&console_lock, flags);
+
+ mdelay(5000);
+ machine_restart(0);
+}
+
+
+void __out_of_line_bug(int line)
+{
+ printk("kernel BUG in header file at line %d\n", line);
+ BUG();
+ for ( ; ; ) ;
+}
--- /dev/null
+/******************************************************************************
+ * keyboard.c
+ *
+ * Driver for IBM PC AT- and PS/2-compatible keyboards.
+ *
+ * This file contains portions of code from Linux.
+ */
+
+#include <asm-i386/io.h>
+#include <asm-i386/irq.h>
+#include <xeno/sched.h>
+#include <xeno/keyhandler.h>
+#include <hypervisor-ifs/kbd.h>
+#include <xeno/event.h>
+#include <xeno/console.h>
+
+/* Hash-defines torn from <linux/pc_keyb.h> and <asm/keyboard.h> */
+
+#define KBD_STATUS_REG 0x64 /* Status register (R) */
+#define KBD_CNTL_REG 0x64 /* Controller command register (W) */
+#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
+
+/* register status bits */
+#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
+#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
+#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
+
+#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
+#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
+#define KBD_STAT_PERR 0x80 /* Parity error */
+
+#define kbd_read_input() inb(KBD_DATA_REG)
+#define kbd_read_status() inb(KBD_STATUS_REG)
+
+#define KEYBOARD_IRQ 1
+#define AUX_IRQ 12
+
+#define kbd_write_output(val) outb(val, KBD_DATA_REG)
+#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
+
+#ifdef CONFIG_XEN_ATTENTION_KEY
+
+static int xen_attention_key_down = 0;
+#define XEN_ATTENTION_KEY 0x46 /* Scroll Lock */
+#define KBD_SCANCODE_KEYUP_MASK 0x80
+
+/* Simple scancode-to-key mappings for internal Xen use. */
+
+static unsigned char keymap_normal[] =
+{
+ 0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t',
+ 'q','w','e','r', 't','y','u','i', 'o','p','[',']','\r', 0 ,'a','s',
+ 'd','f','g','h', 'j','k','l',';', '\'','`', 0 ,'#', 'z','x','c','v',
+ 'b','n','m',',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+};
+
+static unsigned char keymap_shift[] =
+{
+ 0 , 0 ,'!','"', '#','$','%','^', '&','*','(',')', '_','+','\b','\t',
+ 'Q','W','E','R', 'T','Y','U','I', 'O','P','{','}','\r', 0 ,'A','S',
+ 'D','F','G','H', 'J','K','L',':', '@', 0 , 0 ,'~', 'Z','X','C','V',
+ 'B','N','M','<', '>','?', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 ,'|', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+};
+
+
+static int keyboard_shift = 0;
+
+static unsigned char convert_scancode (unsigned char scancode)
+{
+ unsigned char value = 0;
+
+ switch ( scancode )
+ {
+
+ case 0xaa: /* shift (left) UP */
+ case 0xb6: /* shift (right) UP */
+ keyboard_shift = 0;
+ break;
+
+ case 0x2a: /* shift (left) DOWN */
+ case 0x36: /* shift (right) DOWN */
+ keyboard_shift = 1;
+ break;
+
+ default:
+ /* Only process key-up events */
+ if(!(scancode & KBD_SCANCODE_KEYUP_MASK))
+ break;
+ scancode = scancode & ~KBD_SCANCODE_KEYUP_MASK;
+ if (keyboard_shift)
+ value = keymap_shift[scancode];
+ else
+ value = keymap_normal[scancode];
+ break;
+ }
+
+ return value;
+}
+
+#endif /* CONFIG_XEN_ATTENTION_KEY */
+
+
+/* We store kbd events awaiting receive by a guest OS in a ring buffer. */
+#define KBD_RING_SIZE 64
+static int kbd_ring[KBD_RING_SIZE];
+static int kbd_ring_prod = 0;
+static int kbd_ring_cons = 0;
+
+#define KBD_RING_INC(_i) (((_i)+1) & (KBD_RING_SIZE-1))
+#define KBD_RING_FULL (KBD_RING_INC(kbd_ring_prod) == kbd_ring_cons)
+#define KBD_RING_EMPTY (kbd_ring_prod == kbd_ring_cons)
+
+static void kbd_ring_push(unsigned char status, unsigned char scancode)
+{
+ if ( KBD_RING_FULL )
+ return;
+
+ kbd_ring[kbd_ring_prod] = KBD_CODE(scancode, status);
+ kbd_ring_prod = KBD_RING_INC(kbd_ring_prod);
+}
+
+static int kbd_ring_pop(void)
+{
+ int ret;
+
+ if ( KBD_RING_EMPTY )
+ {
+ /* Read directly from controller - no events waiting in ring. */
+ unsigned char status = kbd_read_status();
+ unsigned char scancode = kbd_read_input();
+ ret = KBD_CODE(scancode, status);
+ }
+ else
+ {
+ ret = kbd_ring[kbd_ring_cons];
+ kbd_ring_cons = KBD_RING_INC(kbd_ring_cons);
+ }
+
+ return ret;
+}
+
+
+/*
+ * NB. Lock is essential as there are two distinct interrupts (keyboard + aux).
+ * Also interrupts may disturb guest OS actions.
+ */
+static spinlock_t kbd_lock;
+
+long do_kbd_op(unsigned char op, unsigned char val)
+{
+ unsigned long flags;
+ long ret = -EINVAL;
+
+ if ( !CONSOLE_ISOWNER(current) )
+ return -EPERM;
+
+ spin_lock_irqsave(&kbd_lock, flags);
+
+ switch ( op )
+ {
+ case KBD_OP_WRITEOUTPUT:
+ kbd_write_output(val);
+ ret = 0L;
+ break;
+ case KBD_OP_WRITECOMMAND:
+ kbd_write_command(val);
+ ret = 0L;
+ break;
+ case KBD_OP_READ:
+ ret = kbd_ring_pop();
+ break;
+ }
+
+ spin_unlock_irqrestore(&kbd_lock, flags);
+
+ return ret;
+}
+
+
+static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ unsigned char status=0, scancode;
+ unsigned int work = 1000;
+ unsigned long cpu_mask = 0, flags;
+ struct task_struct *p = CONSOLE_OWNER;
+
+ spin_lock_irqsave(&kbd_lock, flags);
+
+ while ( (--work > 0) && ((status = kbd_read_status()) & KBD_STAT_OBF) )
+ {
+ scancode = kbd_read_input();
+
+#ifdef CONFIG_XEN_ATTENTION_KEY
+ if ( !(status & (KBD_STAT_GTO | KBD_STAT_PERR | KBD_STAT_MOUSE_OBF)) )
+ {
+ if ( (scancode & ~KBD_SCANCODE_KEYUP_MASK) == XEN_ATTENTION_KEY )
+ {
+ xen_attention_key_down = !(scancode & KBD_SCANCODE_KEYUP_MASK);
+ continue;
+ }
+ else if ( xen_attention_key_down )
+ {
+ key_handler *handler;
+ unsigned char key;
+ spin_unlock_irqrestore(&kbd_lock, flags);
+ key = convert_scancode(scancode);
+ if ( key && (handler = get_key_handler(key)) )
+ (*handler)(key, dev_id, regs);
+ spin_lock_irqsave(&kbd_lock, flags);
+ continue;
+ }
+ }
+#endif
+
+ if ( p != NULL )
+ {
+ kbd_ring_push(status, scancode);
+ cpu_mask |= mark_guest_event(p, _EVENT_PS2);
+ }
+ }
+
+ if ( !work )
+ printk(KERN_ERR "xen_keyb: controller jammed (0x%02X).\n", status);
+
+ spin_unlock_irqrestore(&kbd_lock, flags);
+
+ if ( p != NULL )
+ {
+ put_task_struct(p);
+ guest_event_notify(cpu_mask);
+ }
+}
+
+
+
+void initialize_keyboard()
+{
+ spin_lock_init(&kbd_lock);
+
+ if( request_irq(KEYBOARD_IRQ, keyboard_interrupt,
+ SA_NOPROFILE, "keyboard", NULL))
+ {
+ printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ);
+ return;
+ }
+
+ if ( request_irq(AUX_IRQ, keyboard_interrupt,
+ SA_NOPROFILE, "PS/2 Mouse", NULL))
+ {
+ printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ);
+ return;
+ }
+}
+
+++ /dev/null
-#include <asm-i386/io.h>
-#include <asm-i386/irq.h>
-#include <xeno/sched.h>
-#include <xeno/keyhandler.h>
-#include <hypervisor-ifs/kbd.h>
-#include <xeno/event.h>
-#include <xeno/console.h>
-
-/* Hash-defines torn from <linux/pc_keyb.h> and <asm/keyboard.h> */
-
-#define KBD_STATUS_REG 0x64 /* Status register (R) */
-#define KBD_CNTL_REG 0x64 /* Controller command register (W) */
-#define KBD_DATA_REG 0x60 /* Keyboard data register (R/W) */
-
-/* register status bits */
-#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
-#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
-#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
-#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
-
-#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
-#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
-#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
-#define KBD_STAT_PERR 0x80 /* Parity error */
-
-#define kbd_read_input() inb(KBD_DATA_REG)
-#define kbd_read_status() inb(KBD_STATUS_REG)
-
-#define KEYBOARD_IRQ 1
-#define AUX_IRQ 12
-
-#define kbd_write_output(val) outb(val, KBD_DATA_REG)
-#define kbd_write_command(val) outb(val, KBD_CNTL_REG)
-
-#ifdef CONFIG_XEN_ATTENTION_KEY
-
-static int xen_attention_key_down = 0;
-#define XEN_ATTENTION_KEY 0x46 /* Scroll Lock */
-#define KBD_SCANCODE_KEYUP_MASK 0x80
-
-/* Simple scancode-to-key mappings for internal Xen use. */
-
-static unsigned char keymap_normal[] =
-{
- 0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t',
- 'q','w','e','r', 't','y','u','i', 'o','p','[',']','\r', 0 ,'a','s',
- 'd','f','g','h', 'j','k','l',';', '\'','`', 0 ,'#', 'z','x','c','v',
- 'b','n','m',',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
-};
-
-static unsigned char keymap_shift[] =
-{
- 0 , 0 ,'!','"', '#','$','%','^', '&','*','(',')', '_','+','\b','\t',
- 'Q','W','E','R', 'T','Y','U','I', 'O','P','{','}','\r', 0 ,'A','S',
- 'D','F','G','H', 'J','K','L',':', '@', 0 , 0 ,'~', 'Z','X','C','V',
- 'B','N','M','<', '>','?', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
-
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 ,'|', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
- 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
-};
-
-
-static int keyboard_shift = 0;
-
-static unsigned char convert_scancode (unsigned char scancode)
-{
- unsigned char value = 0;
-
- switch ( scancode )
- {
-
- case 0xaa: /* shift (left) UP */
- case 0xb6: /* shift (right) UP */
- keyboard_shift = 0;
- break;
-
- case 0x2a: /* shift (left) DOWN */
- case 0x36: /* shift (right) DOWN */
- keyboard_shift = 1;
- break;
-
- default:
- /* Only process key-up events */
- if(!(scancode & KBD_SCANCODE_KEYUP_MASK))
- break;
- scancode = scancode & ~KBD_SCANCODE_KEYUP_MASK;
- if (keyboard_shift)
- value = keymap_shift[scancode];
- else
- value = keymap_normal[scancode];
- break;
- }
-
- return value;
-}
-
-#endif /* CONFIG_XEN_ATTENTION_KEY */
-
-
-/* We store kbd events awaiting receive by a guest OS in a ring buffer. */
-#define KBD_RING_SIZE 64
-static int kbd_ring[KBD_RING_SIZE];
-static int kbd_ring_prod = 0;
-static int kbd_ring_cons = 0;
-
-#define KBD_RING_INC(_i) (((_i)+1) & (KBD_RING_SIZE-1))
-#define KBD_RING_FULL (KBD_RING_INC(kbd_ring_prod) == kbd_ring_cons)
-#define KBD_RING_EMPTY (kbd_ring_prod == kbd_ring_cons)
-
-static void kbd_ring_push(unsigned char status, unsigned char scancode)
-{
- if ( KBD_RING_FULL )
- return;
-
- kbd_ring[kbd_ring_prod] = KBD_CODE(scancode, status);
- kbd_ring_prod = KBD_RING_INC(kbd_ring_prod);
-}
-
-static int kbd_ring_pop(void)
-{
- int ret;
-
- if ( KBD_RING_EMPTY )
- {
- /* Read directly from controller - no events waiting in ring. */
- unsigned char status = kbd_read_status();
- unsigned char scancode = kbd_read_input();
- ret = KBD_CODE(scancode, status);
- }
- else
- {
- ret = kbd_ring[kbd_ring_cons];
- kbd_ring_cons = KBD_RING_INC(kbd_ring_cons);
- }
-
- return ret;
-}
-
-
-/*
- * NB. Lock is essential as there are two distinct interrupts (keyboard + aux).
- * Also interrupts may disturb guest OS actions.
- */
-static spinlock_t kbd_lock;
-
-long do_kbd_op(unsigned char op, unsigned char val)
-{
- unsigned long flags;
- long ret = -EINVAL;
-
- if ( !CONSOLE_ISOWNER(current) )
- return -EPERM;
-
- spin_lock_irqsave(&kbd_lock, flags);
-
- switch ( op )
- {
- case KBD_OP_WRITEOUTPUT:
- kbd_write_output(val);
- ret = 0L;
- break;
- case KBD_OP_WRITECOMMAND:
- kbd_write_command(val);
- ret = 0L;
- break;
- case KBD_OP_READ:
- ret = kbd_ring_pop();
- break;
- }
-
- spin_unlock_irqrestore(&kbd_lock, flags);
-
- return ret;
-}
-
-
-static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs)
-{
- unsigned char status=0, scancode;
- unsigned int work = 1000;
- unsigned long cpu_mask = 0, flags;
- struct task_struct *p = CONSOLE_OWNER;
-
- spin_lock_irqsave(&kbd_lock, flags);
-
- while ( (--work > 0) && ((status = kbd_read_status()) & KBD_STAT_OBF) )
- {
- scancode = kbd_read_input();
-
-#ifdef CONFIG_XEN_ATTENTION_KEY
- if ( !(status & (KBD_STAT_GTO | KBD_STAT_PERR | KBD_STAT_MOUSE_OBF)) )
- {
- if ( (scancode & ~KBD_SCANCODE_KEYUP_MASK) == XEN_ATTENTION_KEY )
- {
- xen_attention_key_down = !(scancode & KBD_SCANCODE_KEYUP_MASK);
- continue;
- }
- else if ( xen_attention_key_down )
- {
- key_handler *handler;
- unsigned char key;
- spin_unlock_irqrestore(&kbd_lock, flags);
- key = convert_scancode(scancode);
- if ( key && (handler = get_key_handler(key)) )
- (*handler)(key, dev_id, regs);
- spin_lock_irqsave(&kbd_lock, flags);
- continue;
- }
- }
-#endif
-
- if ( p != NULL )
- {
- kbd_ring_push(status, scancode);
- cpu_mask |= mark_guest_event(p, _EVENT_PS2);
- }
- }
-
- if ( !work )
- printk(KERN_ERR "xen_keyb: controller jammed (0x%02X).\n", status);
-
- spin_unlock_irqrestore(&kbd_lock, flags);
-
- if ( p != NULL )
- {
- put_task_struct(p);
- guest_event_notify(cpu_mask);
- }
-}
-
-
-
-void initialize_keyboard()
-{
- spin_lock_init(&kbd_lock);
-
- if( request_irq(KEYBOARD_IRQ, keyboard_interrupt,
- SA_NOPROFILE, "keyboard", NULL))
- {
- printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ);
- return;
- }
-
- if ( request_irq(AUX_IRQ, keyboard_interrupt,
- SA_NOPROFILE, "PS/2 Mouse", NULL))
- {
- printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ);
- return;
- }
-}
-
/* EAX = vector; EBX, ECX, EDX, ESI, EDI = args 1, 2, 3, 4, 5. */
#define __HYPERVISOR_set_trap_table 0
#define __HYPERVISOR_mmu_update 1
-#define __HYPERVISOR_console_write 2
+#define __HYPERVISOR_console_write 2 /* DEPRECATED */
#define __HYPERVISOR_set_gdt 3
#define __HYPERVISOR_stack_switch 4
#define __HYPERVISOR_set_callbacks 5
#define __HYPERVISOR_set_timer_op 20
#define __HYPERVISOR_event_channel_op 21
#define __HYPERVISOR_xen_version 22
+#define __HYPERVISOR_serial_io 23
/* And the trap vector is... */
#define TRAP_INSTR "int $0x82"
#define _EVENT_STOP 6
#define _EVENT_EVTCHN 7
#define _EVENT_VBD_UPD 8
+#define _EVENT_CONSOLE 9 /* This is only for domain-0 initial console. */
/*
* Virtual addresses beyond this are not modifiable by guest OSes. The
#define SCHEDOP_exit 3 /* Exit and kill this domain. */
#define SCHEDOP_stop 4 /* Stop executing this domain. */
+/*
+ * Commands to HYPERVISOR_serial_io().
+ */
+#define SERIALIO_write 0
+#define SERIALIO_read 1
#ifndef __ASSEMBLY__
#ifndef __CONSOLE_H__
#define __CONSOLE_H__
+#include <xeno/spinlock.h>
+
+extern spinlock_t console_lock;
+
/*
* Ownership of console --- currently hardwired to dom0. This is used to see
* who gets the PS/2 keyboard/mouse events
*/
-
-extern int sercon_handle;
-extern int vgacon_enabled;
-
#define CONSOLE_ISOWNER(p) (p->domain == 0)
#define CONSOLE_OWNER (find_domain_by_id(0))
-#define CONSOLE_RING_SIZE 16392
-#define CONSOLE_RING_CLEAR 1
-
-typedef struct console_ring_st
-{
- char buf[CONSOLE_RING_SIZE];
- unsigned int len;
-} console_ring_t;
-
-extern console_ring_t console_ring;
+void set_printk_prefix(const char *prefix);
+#define CONSOLE_RING_CLEAR 1
long read_console_ring(unsigned long, unsigned int, unsigned int);
+void init_console(void);
+void console_endboot(int disable_vga);
+
#endif
static void priv_conwrite(const char *s, unsigned int count)
{
- static char str[256];
- static int pos = 0;
- int len;
+ int rc;
- /* We buffer output until we see a newline, or until the buffer is full. */
- while ( count != 0 )
+ while ( count > 0 )
{
- len = ((sizeof(str) - pos) > count) ? count : sizeof(str) - pos;
- memcpy(str + pos, s, len);
- pos += len;
- s += len;
- count -= len;
- if ( (pos == sizeof(str)) || (str[pos-1] == '\n') )
+ if ( (rc = HYPERVISOR_serial_io(SERIALIO_write, count, s)) > 0 )
{
- (void)HYPERVISOR_console_write(str, pos);
- pos = 0;
+ count -= rc;
+ s += rc;
}
}
}
return ret;
}
-
static inline int HYPERVISOR_mmu_update(mmu_update_t *req, int count)
{
int ret;
return ret;
}
-
-static inline int HYPERVISOR_console_write(const char *str, int count)
-{
- int ret;
- __asm__ __volatile__ (
- TRAP_INSTR
- : "=a" (ret) : "0" (__HYPERVISOR_console_write),
- "b" (str), "c" (count) : "memory" );
-
-
- return ret;
-}
-
static inline int HYPERVISOR_set_gdt(unsigned long *frame_list, int entries)
{
int ret;
return ret;
}
+static inline int HYPERVISOR_serial_io(int cmd, int count, char *str)
+{
+ int ret;
+ __asm__ __volatile__ (
+ TRAP_INSTR
+ : "=a" (ret) : "0" (__HYPERVISOR_serial_io),
+ "b" (cmd), "c" (count), "d" (str) : "memory" );
+
+ return ret;
+}
+
#endif /* __HYPERVISOR_H__ */
static inline void set_in_cr4 (unsigned long mask)
{
- HYPERVISOR_console_write("No set_in_cr4", 13);
+ BUG();
}
static inline void clear_in_cr4 (unsigned long mask)
{
- HYPERVISOR_console_write("No clear_in_cr4", 15);
+ BUG();
}
/*
#endif
CHECK_EMERGENCY_SYNC
#if defined(CONFIG_XENO)
- HYPERVISOR_console_write(buf, strlen(buf));
HYPERVISOR_exit();
#endif
}
+++ /dev/null
-/*
- * linux/kernel/printk.c
- *
- * Copyright (C) 1991, 1992 Linus Torvalds
- *
- * Modified to make sys_syslog() more flexible: added commands to
- * return the last 4k of kernel messages, regardless of whether
- * they've been read or not. Added option to suppress kernel printk's
- * to the console. Added hook for sending the console messages
- * elsewhere, in preparation for a serial line console (someday).
- * Ted Ts'o, 2/11/93.
- * Modified for sysctl support, 1/8/97, Chris Horn.
- * Fixed SMP synchronization, 08/08/99, Manfred Spraul
- * manfreds@colorfullife.com
- * Rewrote bits to get rid of console_lock
- * 01Mar01 Andrew Morton <andrewm@uow.edu.au>
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/smp_lock.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h> /* For in_interrupt() */
-#include <linux/config.h>
-
-#include <asm/uaccess.h>
-
-#if !defined(CONFIG_LOG_BUF_SHIFT) || (CONFIG_LOG_BUF_SHIFT == 0)
-#if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
-#define LOG_BUF_LEN (65536)
-#elif defined(CONFIG_ARCH_S390)
-#define LOG_BUF_LEN (131072)
-#elif defined(CONFIG_SMP)
-#define LOG_BUF_LEN (32768)
-#else
-#define LOG_BUF_LEN (16384) /* This must be a power of two */
-#endif
-#else /* CONFIG_LOG_BUF_SHIFT */
-#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
-#endif
-
-#define LOG_BUF_MASK (LOG_BUF_LEN-1)
-
-#ifndef arch_consoles_callable
-#define arch_consoles_callable() (1)
-#endif
-
-/* printk's without a loglevel use this.. */
-#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
-
-/* We show everything that is MORE important than this.. */
-#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
-#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
-
-DECLARE_WAIT_QUEUE_HEAD(log_wait);
-
-int console_printk[4] = {
- DEFAULT_CONSOLE_LOGLEVEL, /* console_loglevel */
- DEFAULT_MESSAGE_LOGLEVEL, /* default_message_loglevel */
- MINIMUM_CONSOLE_LOGLEVEL, /* minimum_console_loglevel */
- DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */
-};
-
-int oops_in_progress;
-
-/*
- * console_sem protects the console_drivers list, and also
- * provides serialisation for access to the entire console
- * driver system.
- */
-static DECLARE_MUTEX(console_sem);
-struct console *console_drivers;
-
-/*
- * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
- * It is also used in interesting ways to provide interlocking in
- * release_console_sem().
- */
-static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
-
-static char log_buf[LOG_BUF_LEN];
-#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
-
-/*
- * The indices into log_buf are not constrained to LOG_BUF_LEN - they
- * must be masked before subscripting
- */
-static unsigned long log_start; /* Index into log_buf: next char to be read by syslog() */
-static unsigned long con_start; /* Index into log_buf: next char to be sent to consoles */
-static unsigned long log_end; /* Index into log_buf: most-recently-written-char + 1 */
-static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
-
-struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
-static int preferred_console = -1;
-
-/* Flag: console code may call schedule() */
-static int console_may_schedule;
-
-/*
- * Setup a list of consoles. Called from init/main.c
- */
-static int __init console_setup(char *str)
-{
- struct console_cmdline *c;
- char name[sizeof(c->name)];
- char *s, *options;
- int i, idx;
-
- /*
- * Decode str into name, index, options.
- */
- if (str[0] >= '0' && str[0] <= '9') {
- strcpy(name, "ttyS");
- strncpy(name + 4, str, sizeof(name) - 5);
- } else
- strncpy(name, str, sizeof(name) - 1);
- name[sizeof(name) - 1] = 0;
- if ((options = strchr(str, ',')) != NULL)
- *(options++) = 0;
-#ifdef __sparc__
- if (!strcmp(str, "ttya"))
- strcpy(name, "ttyS0");
- if (!strcmp(str, "ttyb"))
- strcpy(name, "ttyS1");
-#endif
- for(s = name; *s; s++)
- if (*s >= '0' && *s <= '9')
- break;
- idx = simple_strtoul(s, NULL, 10);
- *s = 0;
-
- /*
- * See if this tty is not yet registered, and
- * if we have a slot free.
- */
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
- if (strcmp(console_cmdline[i].name, name) == 0 &&
- console_cmdline[i].index == idx) {
- preferred_console = i;
- return 1;
- }
- if (i == MAX_CMDLINECONSOLES)
- return 1;
- preferred_console = i;
- c = &console_cmdline[i];
- memcpy(c->name, name, sizeof(c->name));
- c->options = options;
- c->index = idx;
- return 1;
-}
-
-__setup("console=", console_setup);
-
-/*
- * Commands to do_syslog:
- *
- * 0 -- Close the log. Currently a NOP.
- * 1 -- Open the log. Currently a NOP.
- * 2 -- Read from the log.
- * 3 -- Read all messages remaining in the ring buffer.
- * 4 -- Read and clear all messages remaining in the ring buffer
- * 5 -- Clear ring buffer.
- * 6 -- Disable printk's to console
- * 7 -- Enable printk's to console
- * 8 -- Set level of messages printed to console
- * 9 -- Return number of unread characters in the log buffer
- */
-int do_syslog(int type, char * buf, int len)
-{
- unsigned long i, j, limit, count;
- int do_clear = 0;
- char c;
- int error = 0;
-
- switch (type) {
- case 0: /* Close log */
- break;
- case 1: /* Open log */
- break;
- case 2: /* Read from log */
- error = -EINVAL;
- if (!buf || len < 0)
- goto out;
- error = 0;
- if (!len)
- goto out;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
- goto out;
- error = wait_event_interruptible(log_wait, (log_start - log_end));
- if (error)
- goto out;
- i = 0;
- spin_lock_irq(&logbuf_lock);
- while ((log_start != log_end) && i < len) {
- c = LOG_BUF(log_start);
- log_start++;
- spin_unlock_irq(&logbuf_lock);
- __put_user(c,buf);
- buf++;
- i++;
- spin_lock_irq(&logbuf_lock);
- }
- spin_unlock_irq(&logbuf_lock);
- error = i;
- break;
- case 4: /* Read/clear last kernel messages */
- do_clear = 1;
- /* FALL THRU */
- case 3: /* Read last kernel messages */
- error = -EINVAL;
- if (!buf || len < 0)
- goto out;
- error = 0;
- if (!len)
- goto out;
- error = verify_area(VERIFY_WRITE,buf,len);
- if (error)
- goto out;
- count = len;
- if (count > LOG_BUF_LEN)
- count = LOG_BUF_LEN;
- spin_lock_irq(&logbuf_lock);
- if (count > logged_chars)
- count = logged_chars;
- if (do_clear)
- logged_chars = 0;
- limit = log_end;
- /*
- * __put_user() could sleep, and while we sleep
- * printk() could overwrite the messages
- * we try to copy to user space. Therefore
- * the messages are copied in reverse. <manfreds>
- */
- for(i=0;i < count;i++) {
- j = limit-1-i;
- if (j+LOG_BUF_LEN < log_end)
- break;
- c = LOG_BUF(j);
- spin_unlock_irq(&logbuf_lock);
- __put_user(c,&buf[count-1-i]);
- spin_lock_irq(&logbuf_lock);
- }
- spin_unlock_irq(&logbuf_lock);
- error = i;
- if(i != count) {
- int offset = count-error;
- /* buffer overflow during copy, correct user buffer. */
- for(i=0;i<error;i++) {
- __get_user(c,&buf[i+offset]);
- __put_user(c,&buf[i]);
- }
- }
-
- break;
- case 5: /* Clear ring buffer */
- spin_lock_irq(&logbuf_lock);
- logged_chars = 0;
- spin_unlock_irq(&logbuf_lock);
- break;
- case 6: /* Disable logging to console */
- spin_lock_irq(&logbuf_lock);
- console_loglevel = minimum_console_loglevel;
- spin_unlock_irq(&logbuf_lock);
- break;
- case 7: /* Enable logging to console */
- spin_lock_irq(&logbuf_lock);
- console_loglevel = default_console_loglevel;
- spin_unlock_irq(&logbuf_lock);
- break;
- case 8: /* Set level of messages printed to console */
- error = -EINVAL;
- if (len < 1 || len > 8)
- goto out;
- if (len < minimum_console_loglevel)
- len = minimum_console_loglevel;
- spin_lock_irq(&logbuf_lock);
- console_loglevel = len;
- spin_unlock_irq(&logbuf_lock);
- error = 0;
- break;
- case 9: /* Number of chars in the log buffer */
- spin_lock_irq(&logbuf_lock);
- error = log_end - log_start;
- spin_unlock_irq(&logbuf_lock);
- break;
- default:
- error = -EINVAL;
- break;
- }
-out:
- return error;
-}
-
-asmlinkage long sys_syslog(int type, char * buf, int len)
-{
- if ((type != 3) && !capable(CAP_SYS_ADMIN))
- return -EPERM;
- return do_syslog(type, buf, len);
-}
-
-/*
- * Call the console drivers on a range of log_buf
- */
-static void __call_console_drivers(unsigned long start, unsigned long end)
-{
- struct console *con;
-
- for (con = console_drivers; con; con = con->next) {
- if ((con->flags & CON_ENABLED) && con->write)
- con->write(con, &LOG_BUF(start), end - start);
- }
-}
-
-/*
- * Write out chars from start to end - 1 inclusive
- */
-static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
-{
- if (msg_log_level < console_loglevel && console_drivers && start != end) {
- if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
- /* wrapped write */
- __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
- __call_console_drivers(0, end & LOG_BUF_MASK);
- } else {
- __call_console_drivers(start, end);
- }
- }
-}
-
-/*
- * Call the console drivers, asking them to write out
- * log_buf[start] to log_buf[end - 1].
- * The console_sem must be held.
- */
-static void call_console_drivers(unsigned long start, unsigned long end)
-{
- unsigned long cur_index, start_print;
- static int msg_level = -1;
-
- if (((long)(start - end)) > 0)
- BUG();
-
- cur_index = start;
- start_print = start;
- while (cur_index != end) {
- if ( msg_level < 0 &&
- ((end - cur_index) > 2) &&
- LOG_BUF(cur_index + 0) == '<' &&
- LOG_BUF(cur_index + 1) >= '0' &&
- LOG_BUF(cur_index + 1) <= '7' &&
- LOG_BUF(cur_index + 2) == '>')
- {
- msg_level = LOG_BUF(cur_index + 1) - '0';
- cur_index += 3;
- start_print = cur_index;
- }
- while (cur_index != end) {
- char c = LOG_BUF(cur_index);
- cur_index++;
-
- if (c == '\n') {
- if (msg_level < 0) {
- /*
- * printk() has already given us loglevel tags in
- * the buffer. This code is here in case the
- * log buffer has wrapped right round and scribbled
- * on those tags
- */
- msg_level = default_message_loglevel;
- }
- _call_console_drivers(start_print, cur_index, msg_level);
- msg_level = -1;
- start_print = cur_index;
- break;
- }
- }
- }
- _call_console_drivers(start_print, end, msg_level);
-}
-
-static void emit_log_char(char c)
-{
- LOG_BUF(log_end) = c;
- log_end++;
- if (log_end - log_start > LOG_BUF_LEN)
- log_start = log_end - LOG_BUF_LEN;
- if (log_end - con_start > LOG_BUF_LEN)
- con_start = log_end - LOG_BUF_LEN;
- if (logged_chars < LOG_BUF_LEN)
- logged_chars++;
-}
-
-/*
- * This is printk. It can be called from any context. We want it to work.
- *
- * We try to grab the console_sem. If we succeed, it's easy - we log the output and
- * call the console drivers. If we fail to get the semaphore we place the output
- * into the log buffer and return. The current holder of the console_sem will
- * notice the new output in release_console_sem() and will send it to the
- * consoles before releasing the semaphore.
- *
- * One effect of this deferred printing is that code which calls printk() and
- * then changes console_loglevel may break. This is because console_loglevel
- * is inspected when the actual printing occurs.
- */
-asmlinkage int printk(const char *fmt, ...)
-{
- va_list args;
- unsigned long flags;
- int printed_len;
- char *p;
- static char printk_buf[1024];
- static int log_level_unknown = 1;
-
- if (oops_in_progress) {
- /* If a crash is occurring, make sure we can't deadlock */
- spin_lock_init(&logbuf_lock);
- /* And make sure that we print immediately */
- init_MUTEX(&console_sem);
- }
-
- /* This stops the holder of console_sem just where we want him */
- spin_lock_irqsave(&logbuf_lock, flags);
-
- /* Emit the output into the temporary buffer */
- va_start(args, fmt);
- printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
- va_end(args);
-
-#if 0
- /* Useful if things are going wrong very early in the day. */
- (void)HYPERVISOR_console_write(printk_buf, printed_len);
-#endif
-
- /*
- * Copy the output into log_buf. If the caller didn't provide
- * appropriate log level tags, we insert them here
- */
- for (p = printk_buf; *p; p++) {
- if (log_level_unknown) {
- if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
- emit_log_char('<');
- emit_log_char(default_message_loglevel + '0');
- emit_log_char('>');
- }
- log_level_unknown = 0;
- }
- emit_log_char(*p);
- if (*p == '\n')
- log_level_unknown = 1;
- }
-
- if (!arch_consoles_callable()) {
- /*
- * On some architectures, the consoles are not usable
- * on secondary CPUs early in the boot process.
- */
- spin_unlock_irqrestore(&logbuf_lock, flags);
- goto out;
- }
- if (!down_trylock(&console_sem)) {
- /*
- * We own the drivers. We can drop the spinlock and let
- * release_console_sem() print the text
- */
- spin_unlock_irqrestore(&logbuf_lock, flags);
- console_may_schedule = 0;
- release_console_sem();
- } else {
- /*
- * Someone else owns the drivers. We drop the spinlock, which
- * allows the semaphore holder to proceed and to call the
- * console drivers with the output which we just produced.
- */
- spin_unlock_irqrestore(&logbuf_lock, flags);
- }
-out:
- return printed_len;
-}
-EXPORT_SYMBOL(printk);
-
-/**
- * acquire_console_sem - lock the console system for exclusive use.
- *
- * Acquires a semaphore which guarantees that the caller has
- * exclusive access to the console system and the console_drivers list.
- *
- * Can sleep, returns nothing.
- */
-void acquire_console_sem(void)
-{
- if (in_interrupt())
- BUG();
- down(&console_sem);
- console_may_schedule = 1;
-}
-EXPORT_SYMBOL(acquire_console_sem);
-
-/**
- * release_console_sem - unlock the console system
- *
- * Releases the semaphore which the caller holds on the console system
- * and the console driver list.
- *
- * While the semaphore was held, console output may have been buffered
- * by printk(). If this is the case, release_console_sem() emits
- * the output prior to releasing the semaphore.
- *
- * If there is output waiting for klogd, we wake it up.
- *
- * release_console_sem() may be called from any context.
- */
-void release_console_sem(void)
-{
- unsigned long flags;
- unsigned long _con_start, _log_end;
- unsigned long must_wake_klogd = 0;
-
- for ( ; ; ) {
- spin_lock_irqsave(&logbuf_lock, flags);
- must_wake_klogd |= log_start - log_end;
- if (con_start == log_end)
- break; /* Nothing to print */
- _con_start = con_start;
- _log_end = log_end;
- con_start = log_end; /* Flush */
- spin_unlock_irqrestore(&logbuf_lock, flags);
- call_console_drivers(_con_start, _log_end);
- }
- console_may_schedule = 0;
- up(&console_sem);
- spin_unlock_irqrestore(&logbuf_lock, flags);
- if (must_wake_klogd && !oops_in_progress)
- wake_up_interruptible(&log_wait);
-}
-
-/** console_conditional_schedule - yield the CPU if required
- *
- * If the console code is currently allowed to sleep, and
- * if this CPU should yield the CPU to another task, do
- * so here.
- *
- * Must be called within acquire_console_sem().
- */
-void console_conditional_schedule(void)
-{
- if (console_may_schedule && current->need_resched) {
- set_current_state(TASK_RUNNING);
- schedule();
- }
-}
-
-void console_print(const char *s)
-{
- printk(KERN_EMERG "%s", s);
-}
-EXPORT_SYMBOL(console_print);
-
-void console_unblank(void)
-{
- struct console *c;
-
- /*
- * Try to get the console semaphore. If someone else owns it
- * we have to return without unblanking because console_unblank
- * may be called in interrupt context.
- */
- if (down_trylock(&console_sem) != 0)
- return;
- console_may_schedule = 0;
- for (c = console_drivers; c != NULL; c = c->next)
- if ((c->flags & CON_ENABLED) && c->unblank)
- c->unblank();
- release_console_sem();
-}
-EXPORT_SYMBOL(console_unblank);
-
-/*
- * The console driver calls this routine during kernel initialization
- * to register the console printing procedure with printk() and to
- * print any messages that were printed by the kernel before the
- * console driver was initialized.
- */
-void register_console(struct console * console)
-{
- int i;
- unsigned long flags;
-
- /*
- * See if we want to use this console driver. If we
- * didn't select a console we take the first one
- * that registers here.
- */
- if (preferred_console < 0) {
- if (console->index < 0)
- console->index = 0;
- if (console->setup == NULL ||
- console->setup(console, NULL) == 0) {
- console->flags |= CON_ENABLED | CON_CONSDEV;
- preferred_console = 0;
- }
- }
-
- /*
- * See if this console matches one we selected on
- * the command line.
- */
- for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
- if (strcmp(console_cmdline[i].name, console->name) != 0)
- continue;
- if (console->index >= 0 &&
- console->index != console_cmdline[i].index)
- continue;
- if (console->index < 0)
- console->index = console_cmdline[i].index;
- if (console->setup &&
- console->setup(console, console_cmdline[i].options) != 0)
- break;
- console->flags |= CON_ENABLED;
- console->index = console_cmdline[i].index;
- if (i == preferred_console)
- console->flags |= CON_CONSDEV;
- break;
- }
-
- if (!(console->flags & CON_ENABLED))
- return;
-
- /*
- * Put this console in the list - keep the
- * preferred driver at the head of the list.
- */
- acquire_console_sem();
- if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
- console->next = console_drivers;
- console_drivers = console;
- } else {
- console->next = console_drivers->next;
- console_drivers->next = console;
- }
- if (console->flags & CON_PRINTBUFFER) {
- /*
- * release_console_sem() will print out the buffered messages for us.
- */
- spin_lock_irqsave(&logbuf_lock, flags);
- con_start = log_start;
- spin_unlock_irqrestore(&logbuf_lock, flags);
- }
- release_console_sem();
-}
-EXPORT_SYMBOL(register_console);
-
-int unregister_console(struct console * console)
-{
- struct console *a,*b;
- int res = 1;
-
- acquire_console_sem();
- if (console_drivers == console) {
- console_drivers=console->next;
- res = 0;
- } else {
- for (a=console_drivers->next, b=console_drivers ;
- a; b=a, a=b->next) {
- if (a == console) {
- b->next = a->next;
- res = 0;
- break;
- }
- }
- }
-
- /* If last console is removed, we re-enable picking the first
- * one that gets registered. Without that, pmac early boot console
- * would prevent fbcon from taking over.
- */
- if (console_drivers == NULL)
- preferred_console = -1;
-
-
- release_console_sem();
- return res;
-}
-EXPORT_SYMBOL(unregister_console);
-
-/**
- * tty_write_message - write a message to a certain tty, not just the console.
- *
- * This is used for messages that need to be redirected to a specific tty.
- * We don't put it into the syslog queue right now maybe in the future if
- * really needed.
- */
-void tty_write_message(struct tty_struct *tty, char *msg)
-{
- if (tty && tty->driver.write)
- tty->driver.write(tty, 0, msg, strlen(msg));
- return;
-}